package com.hexus.eve.actions;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.hexus.eve.entities.Group;
import com.hexus.eve.entities.Icon;
import com.hexus.eve.entities.MarketGroup;
import com.hexus.eve.entities.Type;
import com.hexus.eve.utils.MarketGroupUtils;
import com.hexus.eve.utils.TranslationUtils;
import com.opensymphony.xwork2.ActionSupport;

public class Search extends ActionSupport{
	private static final long serialVersionUID = 1L;

	@Autowired
	TranslationUtils translationUtils;
	
	@Autowired
	MarketGroupUtils marketGroupUtils;
	
	private static final Integer PAGES_TO_DISPLAY = 3;
	private static final Integer ROWS_PER_PAGE = 15;

	private final static String QUERY_BEGINING = "SELECT TOP(:rowsPerPage) * FROM " 
			+"("
			+"SELECT ROW_NUMBER() OVER (ORDER BY CHARINDEX(:name, typeName), typeName) AS RowNumber, CHARINDEX(:name, typeName) as relevancy, *, totalRows=Count(*) OVER() "
			+"FROM invTypes WHERE published=1";
	private final static String QUERY_END = ") _tmpInlineView "
			+"WHERE RowNumber > :startRow "		
			+"ORDER BY relevancy, typeName";
	
	private String name = "";
	
	private List<Type> results;
	
	private Integer page = 1;
	private Integer totalPages = 0;
	private Integer totalRows = 0;
	private Integer marketGroupId;
	private Integer groupId;
	
	@Autowired
	private SessionFactory sessionFactory;
	
	public String execute() {
		results = new ArrayList<Type>();
		
		Session session = sessionFactory.openSession();
		String query = QUERY_BEGINING;
		if(name != null && !"".equals(name)) {
			query += " AND CHARINDEX(:name, typeName) > 0"; 
		}
		if(marketGroupId != null) {
			query += " AND marketGroupID=:marketGroupID";
		}
		if(groupId != null) {
			query += " AND groupID=:groupID";
		}
		query += QUERY_END;
		
		Query sqlQuery = session.createSQLQuery(query)
			.addScalar("totalRows", Hibernate.INTEGER)
			.addScalar("typeID", Hibernate.INTEGER)
			.addScalar("typeName", Hibernate.STRING)
			.addScalar("iconID", Hibernate.INTEGER)
			.setString("name", name)
			.setInteger("rowsPerPage", ROWS_PER_PAGE)
			.setInteger("startRow", (page - 1) * ROWS_PER_PAGE);
		
		if(marketGroupId != null) {
			sqlQuery.setInteger("marketGroupID", marketGroupId);
		}
		if(groupId != null) {
			sqlQuery.setInteger("groupID", groupId);
		}
		
		@SuppressWarnings("unchecked")
		List<Object[]> items = sqlQuery.list();
		
		for (Object[] item: items) {
				Type type = new Type();
				type.setId((Integer)item[1]);
				type.setName((String)item[2]);
				
				Integer iconID = (Integer)item[3];
				if(iconID != null)
					type.setIcon((Icon)session.get(Icon.class, iconID));
				
				results.add(type);
		}
		translationUtils.translate(results, getLocale());
		if(results.size() > 0) {
			totalRows = (Integer)items.get(0)[0];
			totalPages = (totalRows - 1) / ROWS_PER_PAGE + 1;		
		}
		
		session.close();
		
		return SUCCESS; 
	}
	
	
	public Integer getMarketGroupId() {
		return marketGroupId;
	}


	public void setMarketGroupId(Integer marketGroupId) {
		this.marketGroupId = marketGroupId;
	}
	
	public Integer getGroupId() {
		return groupId;
	}
	
	public Group getGroup() {
		Group group = null;
		if(groupId != null) {
			Session session = sessionFactory.openSession();
			try {
				group = (Group) session.get(Group.class, groupId);
				translationUtils.translate(group, getLocale());
			}
			catch(Exception ex) {
				Logger logger = Logger.getLogger(this.getClass().getName());
				logger.error(ex.getMessage());
				ex.printStackTrace();
			}
			finally {
				session.close();
			}
		}
		return group;
	}


	public void setGroupId(Integer groupId) {
		this.groupId = groupId;
	}


	public MarketGroup getMarketGroup() {
		MarketGroup mg = marketGroupUtils.getMarketGroup(marketGroupId);
		translationUtils.translate(mg, getLocale());
		return mg;
	}
	
	public List<MarketGroup> getMarketGroupParents(){		
		List<MarketGroup> mg = getMarketGroup().getParentsAsList();
		translationUtils.translate(mg, getLocale());
		return mg;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name.trim();
	}

	public List<Type> getResults() {
		return results;
	}

	public void setResults(List<Type> results) {
		this.results = results;
	}
	
	public void setInputType(String inputTypeName) {
		this.name = inputTypeName.trim();
	}

	public Integer getPage() {
		return page;
	}

	public void setPage(Integer page) {
		this.page = (page < 1) ? 1 : page;
	}


	public Integer getTotalPages() {
		return totalPages;
	}

	public Integer getStartPage(){
		Integer startPage = Math.max(1, page - PAGES_TO_DISPLAY);
		Integer upperLimit = Math.max(1, getTotalPages() - PAGES_TO_DISPLAY * 2 + 1);
		startPage = (startPage > upperLimit) ? upperLimit : startPage;
		return startPage;
	}

	public Integer getEndPage(){
		Integer endPage = Math.min(page + PAGES_TO_DISPLAY, totalPages);
		Integer lowerLimit = Math.min(PAGES_TO_DISPLAY * 2 + 1, totalPages);
		endPage = (endPage < lowerLimit) ? lowerLimit : endPage;
		return endPage;
	}
	
	public List<Integer> getNavigationPages(){
		List<Integer> navigationPages = new ArrayList<Integer>();
		
		for(Integer i = getStartPage(); i <= getEndPage(); i++)
			navigationPages.add(i);
		
		return navigationPages;
	}


	public Integer getTotalRows() {
		return totalRows;
	}


	public void setTotalRows(Integer totalRows) {
		this.totalRows = totalRows;
	}
}
